package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.base.service.IUserService;
import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.CarPackageAuditMapper;
import cn.wolfcode.car.business.mapper.CarPackageAuditMapper;
import cn.wolfcode.car.business.query.CarPackageAuditQuery;
import cn.wolfcode.car.business.query.CarPackageAuditQuery;
import cn.wolfcode.car.business.service.IBpmnInfoService;
import cn.wolfcode.car.business.service.ICarPackageAuditService;
import cn.wolfcode.car.business.service.IServiceItemService;
import cn.wolfcode.car.business.service.IStatementItemService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.config.SystemConfig;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.common.util.Convert;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class CarPackageAuditServiceImpl extends ServiceImpl<CarPackageAuditMapper, CarPackageAudit> implements ICarPackageAuditService {

    @Resource
    private CarPackageAuditMapper carPackageAuditMapper;
    @Autowired
    private IUserService userService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private IBpmnInfoService bpmnInfoService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private IServiceItemService serviceItemService;
    @Autowired
    private TaskService taskService;

    /*
      select id, service_item_name, service_item_id, service_item_info, service_item_price,
             instance_id, creator, auditor_id, bpmnInfo_id, info, status, audit_time, create_time
      from bus_car_package_audit
      <where>
        <if test="auditorId != null">
          and auditor_id = ${auditorId}
        </if>
        <if test="status != null">
          and status = ${status}
        </if>
        <if test="beginTime != null">
          and audit_time &gt;= #{beginTime}
        </if>
        <if test="endTime != null">
          and audit_time &lt;= #{endTime}
        </if>
     */
    @Override
    public TablePageInfo<CarPackageAudit> query(CarPackageAuditQuery qo) {
        IPage<CarPackageAudit> page = new Page<>(qo.getPageNum(), qo.getPageSize());
        LambdaQueryWrapper<CarPackageAudit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(qo.getAuditorId() != null, CarPackageAudit::getAuditorId, qo.getAuditorId())
                .eq(qo.getStatus() != null, CarPackageAudit::getStatus, qo.getStatus())
                .eq(qo.getAutPerson() != null,CarPackageAudit::getAutPerson,qo.getAutPerson())
                .ge(qo.getBeginTime() != null,CarPackageAudit::getAuditTime,qo.getBeginTime())
                .le(qo.getEndTime() != null,CarPackageAudit::getAuditTime,qo.getEndTime());
        IPage<CarPackageAudit> page1 = super.page(page, wrapper);
        List<CarPackageAudit> carPackageAudits = page1.getRecords();
        carPackageAudits.forEach(c ->
        {c.setAuditor(userService.get(c.getAuditorId()));c.setServiceItem(serviceItemService.get(c.getServiceItemId()));}
        );
        return new TablePageInfo<>(page1);
    }


    @Override
    public boolean save(CarPackageAudit carPackageAudit) {
        carPackageAuditMapper.insert(carPackageAudit);
        return true;
    }

    @Override
    public CarPackageAudit get(Long id) {
        //select id, service_item_name, service_item_id, service_item_info, service_item_price,
        //    instance_id, creator, auditor_id, bpmnInfo_id, info, status, audit_time, create_time
        //    from bus_car_package_audit
        //    where id = #{id}
        return carPackageAuditMapper.selectById(id);
    }

    @Override
    public void update(CarPackageAudit carPackageAudit) {
        //update bus_car_package_audit
        //    set service_item_name = #{serviceItemName},
        //      service_item_id = #{serviceItemId},
        //      service_item_info = #{serviceItemInfo},
        //      service_item_price = #{serviceItemPrice},
        //      instance_id = #{instanceId},
        //      creator = #{creator},
        //      auditor_id = #{auditorId},
        //      bpmnInfo_id = #{bpmnInfoId},
        //      info = #{info},
        //      status = #{status},
        //      audit_time = #{auditTime},
        //      create_time = #{createTime}
        //    where id = #{id}
        carPackageAuditMapper.updateById(carPackageAudit);
    }

    @Override
    public void deleteBatch(String ids) {
        Long[] dictIds = Convert.toLongArray(ids);
        for (Long dictId : dictIds) {
            //delete from bus_car_package_audit where id = #{id}
            carPackageAuditMapper.deleteById(dictId);
        }
    }

    @Override
    public List<CarPackageAudit> list() {
        return carPackageAuditMapper.selectList(null);
    }

    @Override
    @Transactional
    public InputStream getProcessImgByAuditId(Long id) {
        CarPackageAudit carPackageAudit = this.get(id);
        //获取审核对象的流程id
        String instanceId = carPackageAudit.getInstanceId();
        List<String> highLightedActivities;
        //如果单前状态是审核中
        if (carPackageAudit.getStatus().equals(CarPackageAudit.STATUS_IN_ROGRESS)) {
            //如果当前是运行中，则需要高亮点运行节点
            //获取当前运行的任务
            highLightedActivities = runtimeService.getActiveActivityIds(instanceId);
        } else {
            //如果当前是审核通过/拒绝，都不需要高亮点运行节点
            highLightedActivities = new ArrayList<>();
        }
        //通过bpmnInfoId获取到bpmnInfo对象
        BpmnInfo bpmnInfo = bpmnInfoService.get(carPackageAudit.getBpmnInfoId());
        BpmnModel bpmnModel = repositoryService.getBpmnModel(bpmnInfo.getActProcessId());
        DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        return generator.generateDiagram(bpmnModel, highLightedActivities, Collections.EMPTY_LIST, "宋体", "宋体", "宋体");
    }

    @Override
    public void cancelApply(Long id) {
        CarPackageAudit carPackageAudit = this.get(id);
        if (carPackageAudit.getStatus().equals(ServiceItem.AUDITSTATUS_AUDITING)) {
            throw new BusinessException("只有在审核中才能撤销申请");
        }
        //update bus_car_package_audit set status = #{status} where id = #{id}
        LambdaUpdateWrapper<CarPackageAudit> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(CarPackageAudit::getId,id).set(CarPackageAudit::getStatus,CarPackageAudit.STATUS_CANCEL);
        carPackageAuditMapper.update(null,wrapper);
        serviceItemService.changeAuditStatus(carPackageAudit.getServiceItemId(), ServiceItem.AUDITSTATUS_REPLY);
        runtimeService.deleteProcessInstance(carPackageAudit.getInstanceId(), "撤销审核");
    }

    @Override
    public void audit(Long id, Integer auditStatus, String info) {
        CarPackageAudit carPackageAudit = this.get(id);
        //如果状态不是审核中，则不能同意或者拒绝
        if (carPackageAudit == null || !carPackageAudit.getStatus().equals(CarPackageAudit.STATUS_IN_ROGRESS)) {
            throw new BusinessException("只有在审核状态才能处理该申请");
        }
        //查询当前的审核人
        String userName = ShiroUtils.getUser().getUserName();
        //从前端页面audit.html中，同意代表是2，拒绝代表是1，如果当前审核同意
        if (auditStatus == 2) {
            info = "[" + userName + "]" + "同意审批：意见" + info;
        } else {
            info = "[" + userName + "]" + "拒绝审批：意见" + info;
        }
        carPackageAudit.setInfo(carPackageAudit.getInfo() + "<br>" + info);
        Task task = taskService.createTaskQuery().processInstanceId(carPackageAudit.getInstanceId()).singleResult();
        //设置审核操作同意与否参数；variableName："auditStatus"是bpmn文件里的同意/拒绝变量对应的名称，第三个参数是前台点击的同意或者拒绝的值
        taskService.setVariable(task.getId(), "auditStatus", auditStatus);
        //设置审批备注
        taskService.addComment(task.getId(), carPackageAudit.getInstanceId(), info);
        //把当前任务完成
        taskService.complete(task.getId());
        //获取下一个节点的申核人
        Task nextTask = taskService.createTaskQuery().processInstanceId(carPackageAudit.getInstanceId()).singleResult();
        if (CarPackageAudit.STATUS_PASS.equals(auditStatus)) {
            if (nextTask != null) {
                //金额大于3000需要下一个审核人审核
                carPackageAudit.setAuditorId(Long.valueOf(nextTask.getAssignee()));
                carPackageAudit.setAuditTime(new Date());
            } else {
                //金额小于3000，当前审核人可以审核通过
                carPackageAudit.setStatus(CarPackageAudit.STATUS_PASS);
                serviceItemService.changeAuditStatus(carPackageAudit.getServiceItemId(), ServiceItem.AUDITSTATUS_APPROVED);
            }
        } else {
            //审核拒绝
            carPackageAudit.setAuditorId(null);
            carPackageAudit.setStatus(CarPackageAudit.STATUS_REJECT);
            serviceItemService.changeAuditStatus(carPackageAudit.getServiceItemId(), ServiceItem.AUDITSTATUS_REPLY);
        }
        carPackageAuditMapper.updateById(carPackageAudit);
    }
}




